# -*- coding: utf-8 -*-
# בש״ד
#
# Miramar CMS for Django - Part of the Cuba Libre Project
# Copyright (C) 2009, Joshua "jag" Ginsberg <jag@flowtheory.net>
# 
# Por mi amor, que inspira a mi cada respiración y que echa de Cuba
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from django.test import TestCase
from django.test.client import Client
from django.contrib.auth.models import User, Permission
from django.contrib.redirects.models import Redirect
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.conf import settings as site_settings
from django.db import connection
from miramar.models import Page, PageVersion
from miramar import api
from miramar.plugins import *
from miramar import settings
from miramar import signals

# A signal handler to ensure the cms_event signal gets sent when we think it
# did

class SignalFiredFlag(object):
    def __init__(self):
        self.signal_queue = []
    
    def __call__(self, sender=None, event=None, **kwargs):
        self.signal_queue.append((event, sender))
    
    def reset(self):
        self.signal_queue = []
    
    def fired(self):
        if self.signal_queue:
            to_return = self.signal_queue
            self.signal_queue = []
            return to_return
        else:
            return False

signal_test = SignalFiredFlag()
signals.cms_event.connect(signal_test)    

class TestPageDetail(TestCase):
    fixtures = ['view_tests.json']
    
    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        create_page = Permission.objects.get(codename='add_page')
        writer.user_permissions.add(create_page)
        self.writer = writer

    def test_anonymous_page_detail(self):
        c = Client()
        response = c.get(reverse('miramar_page_detail', args=['test']))
        self.assertEqual(response.status_code, 200)
        
        # cannot see by version tag
        response = c.get(reverse('miramar_page_detail_with_tag',
                                 args=['test', 'updated']))
        self.assertEqual(response.status_code, 404)
        
        # cannot see by version tag and revision id
        response = c.get(reverse('miramar_page_detail_with_revision',
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': 1}))
        self.assertEqual(response.status_code, 404)
        
        # 404 for non existent page
        response = c.get(reverse('miramar_page_detail',
                                 args=['does-not-exist']))
        self.assertEqual(response.status_code, 404)
    
    def test_non_published_version_detail(self):
        c = Client()
        c.login(username='staff', password='foobar')
        self.assertTrue(User.objects.get(username='staff').is_staff)
        response = c.get(reverse('miramar_page_detail_with_tag',
                                 args=['test', 'updated']))
        self.assertEqual(response.status_code, 200)
        response = c.get(reverse('miramar_page_detail_with_revision',
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': 1}))
        self.assertEqual(response.status_code, 200)
        # 404 for non existent page
        response = c.get(reverse('miramar_page_detail',
                                 args=['does-not-exist']))
        self.assertEqual(response.status_code, 404)
    
    def test_non_existant_page_redirects_to_create(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_page_detail',
                                 args=['does-not-exist']))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_create', kwargs={'slug': 'does-not-exist'})))
        self.assertEqual(self.writer.message_set.all().count(),
                         1)
    
    def test_non_existant_page_with_redirect(self):
        Redirect.objects.create(site=Site.objects.get_current(),
                                old_path='/old-path/',
                                new_path='/new-path/')
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_page_detail',
                                 args=['old-path']))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_create', kwargs={'slug': 'old-path'})))
        self.assertEqual(self.writer.message_set.all().count(),
                         2)
        

class TestPageCreate(TestCase):
    
    fixtures = ['view_tests.json']

    def setUp(self):
        self.staff = User.objects.create_user('staff',
                                              'staff@example.com',
                                              'foobar')
        self.staff.is_staff = True
        self.staff.save()
        self.writer = User.objects.create_user('writer',
                                               'writer@example.com',
                                               'foobar')
        create_page = Permission.objects.get(codename='add_page')
        self.writer.user_permissions.add(create_page)
        signal_test.reset()
    
    def test_page_create_permissions(self):
        c = Client()
        # unauthenticated can't create
        response = c.get(reverse('miramar_page_create', args=['new-page']))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users can't create
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_page_create', args=['new-page']))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
                
        # privileged user can create
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_page_create', args=['new-page']))
        self.assertEqual(response.status_code, 200)

    def test_no_duplicate_slugs(self):
        page_obj = Page.on_site.get(slug__iexact=u'test')
        c = Client()
        # privileged user cannot create duplicate
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_page_create', args=['test']))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].lower().endswith(
            page_obj.get_absolute_url().lower()))
        self.assertFalse(signal_test.fired())
        # test case insensitivity of slug
        response = c.get(reverse('miramar_page_create', args=['TeST']))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].lower().endswith(
            page_obj.get_absolute_url().lower()))
        self.assertFalse(signal_test.fired())
    
    def test_create_post(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(
            reverse('miramar_page_create', args=['new-page']), 
            {'slug': 'new-page',
             'title': 'New Page',
             'site': 1,
             'markup_engine': 'net.skwx.cubalibre.miramar.MarkdownEngine'})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_pageversion_update',
                    kwargs={'slug': 'new-page',
                            'version_tag': settings.DEFAULT_VERSION_TAG})))
        new_page = Page.on_site.get(slug__iexact='new-page')
        self.assertEqual(new_page.slug, u'new-page')
        self.assertEqual(new_page.title, u'New Page')
        self.assertEqual(new_page.created_by, self.writer)
        self.assertEqual(new_page.markup_engine.component_id,
                         'net.skwx.cubalibre.miramar.MarkdownEngine')
        # There should have been PAGE_CREATED and PAGEVERSION_CREATED signals
        signal_data = signal_test.fired()
        self.assert_(signal_data)
        self.assertEqual(len(signal_data), 2)
        self.assert_((signals.PAGE_CREATED, new_page) in signal_data)
        self.assert_((signals.PAGEVERSION_CREATED, 
                      new_page.pageversion_set.get()) in signal_data)

class TestPageVersionBranch(TestCase):
    fixtures = ['view_tests.json']

    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        branch_page = Permission.objects.get(codename='can_branch_pageversion')
        writer.user_permissions.add(branch_page)
        self.writer = writer
        signal_test.reset()

    def test_branch_permissions(self):
        c = Client()
        # anonymous of course can't branch
        response = c.get(reverse('miramar_pageversion_branch', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users may not branch
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_pageversion_branch', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])

        # privileged user can branch
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_branch', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 200)

    def test_no_duplicate_version_tag(self):
        c = Client()
        
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_pageversion_branch',
                                  kwargs={'slug': 'test',
                                          'version_tag': 'default',
                                          'revision': '1'}),
                          {'version_tag': 'default'})
        self.assertEqual(response.status_code, 200)
        self.assert_('version_tag' in response.context[0]['form'].errors)
    
    def test_branch_operation(self):
        c = Client()
        
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_pageversion_branch',
                                  kwargs={'slug': 'test',
                                          'version_tag': 'default',
                                          'revision': '1'}),
                          {'version_tag': 'new-version'})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_pageversion_update',
                    kwargs={'slug': 'test',
                            'version_tag': 'new-version'})))
        new_pageversion = PageVersion.objects.get(page__slug__iexact='test',
                                                  version_tag='new-version',
                                                  revision=1)
        self.assertEqual(new_pageversion.author, self.writer)
        self.assert_('default' in new_pageversion.comment)
        self.assertNotEqual(new_pageversion.page.published_version,
                            new_pageversion)
        self.assertFalse(new_pageversion.approved)
        signal_data = signal_test.fired()
        self.assertEqual(len(signal_data), 1)
        self.assertEqual([(signals.PAGEVERSION_CREATED, new_pageversion)],
                         signal_data)
        
class TestPageUpdate(TestCase):
    fixtures = ['view_tests.json']

    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        update_page = Permission.objects.get(codename='change_page')
        writer.user_permissions.add(update_page)
        self.writer = writer
        signal_test.reset()
    
    def test_update_permissions(self):
        c = Client()
        
        response = c.get(reverse('miramar_page_update',
                                 kwargs={'slug': 'test'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users may not update
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_page_update', 
                                 kwargs={'slug': 'test'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])

        # privileged user can update
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_page_update', 
                                 kwargs={'slug': 'test'}))
        self.assertEqual(response.status_code, 200)

    def test_update_page_form(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_page_update', 
                                  kwargs={'slug': 'test'}),
                          {'title': u'',
                           'site': u'',
                           'markup_engine': u''})
        self.assertEqual(response.status_code, 200)
        self.assert_('title' in response.context[0]['form'].errors)
        self.assert_('site' in response.context[0]['form'].errors)
        self.assert_('markup_engine' in response.context[0]['form'].errors)            

    def test_update_page(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_page_update', 
                                  kwargs={'slug': 'test'}),
                          {'title': u'Changed title',
                           'site': u'1',
                           'markup_engine': u'net.skwx.cubalibre.miramar.MarkdownEngine'})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        new_page_obj = Page.on_site.get(title=u'Changed title')        
        self.assertEqual(new_page_obj.slug.lower(), u'test')
        signal_data = signal_test.fired()
        self.assertEqual(len(signal_data), 1)
        self.assertEqual([(signals.PAGE_UPDATED, new_page_obj)],
                         signal_data)

class TestRenamePage(TestCase):
    fixtures = ['view_tests.json']

    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        update_page = Permission.objects.get(codename='change_page')
        writer.user_permissions.add(update_page)
        self.writer = writer
        signal_test.reset()
    
    def test_rename_permissions(self):
        c = Client()
        
        # anonymous cannot rename
        response = c.get(reverse('miramar_page_rename',
                                 kwargs={'slug': 'test'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users may not rename
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_page_rename', 
                                 kwargs={'slug': 'test'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])

        # privileged user can rename
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_page_rename', 
                                 kwargs={'slug': 'test'}))
        self.assertEqual(response.status_code, 200)

    def test_rename_page_with_redirect(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_page_rename', 
                                  kwargs={'slug': 'test'}),
                          {'new_slug': u'renamed',
                           'create_redirect': '1'})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'renamed'})))
        page_obj = Page.on_site.get(slug__iexact='renamed')
        redirect_obj = Redirect.objects.get(old_path=reverse(
            'miramar_page_detail', 
            kwargs={'slug': 'test'}),
            site=Site.objects.get_current())
        signal_data = signal_test.fired()
        self.assertEqual(len(signal_data), 1)
        self.assertEqual([(signals.PAGE_RENAMED, page_obj)],
                         signal_data)
    
    def test_rename_page_without_redirect(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_page_rename', 
                                  kwargs={'slug': 'test'}),
                          {'new_slug': u'renamed',
                           'create_redirect': '0'})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'renamed'})))
        page_obj = Page.on_site.get(slug__iexact='renamed')
        self.assertRaises(Redirect.DoesNotExist,
                          Redirect.objects.get,
                          old_path=reverse(
                              'miramar_page_detail', 
                              kwargs={'slug': 'test'}),
                          site=Site.objects.get_current())
        signal_data = signal_test.fired()
        self.assertEqual(len(signal_data), 1)
        self.assertEqual([(signals.PAGE_RENAMED, page_obj)],
                         signal_data)

    def test_rename_page_form(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_page_rename', 
                                  kwargs={'slug': 'test'}),
                          {'new_slug': u'',
                           'create_redirect': '0'})
        self.assertEqual(response.status_code, 200)
        self.assert_('new_slug' in response.context[0]['form'].errors)
        response = c.post(reverse('miramar_page_rename', 
                                  kwargs={'slug': 'test'}),
                          {'new_slug': u'invalid slug',
                           'create_redirect': '0'})
        self.assertEqual(response.status_code, 200)
        self.assert_('new_slug' in response.context[0]['form'].errors)
    
    def test_rename_page_to_same_name(self):
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_page_rename', 
                                  kwargs={'slug': 'test'}),
                          {'new_slug': u'test',
                           'create_redirect': '1'})
        self.assertEqual(response.status_code, 200)
        self.assert_('new_slug' in response.context[0]['form'].errors)
        self.assertRaises(Redirect.DoesNotExist,
                          Redirect.objects.get,
                          old_path=reverse(
                              'miramar_page_detail', 
                              kwargs={'slug': 'test'}),
                          site=Site.objects.get_current())
        signal_data = signal_test.fired()
        self.assertFalse(signal_data)    

class TestPageVersionRevise(TestCase):
    fixtures = ['view_tests.json']

    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        editor = User.objects.create_user('editor',
                                          'editor@example.com',
                                          'foobar')
        revise_page = Permission.objects.get(codename='can_revise_pageversion')
        editor.user_permissions.add(revise_page)
        writer.user_permissions.add(revise_page)
        self.writer = writer
        self.editor = editor
        signal_test.reset()

    def test_revise_permissions(self):
        c = Client()
        # anonymous of course can't revise
        response = c.get(reverse('miramar_pageversion_update', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users may not revise
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_pageversion_update', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])

        # privileged user can revise
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_update', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default'}))
        self.assertEqual(response.status_code, 200)
    
    def test_update_page_form(self):
        c = Client()
        c.login(username='editor', password='foobar')
        response = c.post(reverse('miramar_pageversion_update', 
                                  kwargs={'slug': 'test',
                                          'version_tag': 'default'}),
                          {'body': u'',
                           'comment': u'Empty body does not fly'})
        self.assertEqual(response.status_code, 200)
        self.assert_('body' in response.context[0]['form'].errors)
    
    def test_update_page(self):
        c = Client()
        c.login(username='editor', password='foobar')
        response = c.post(reverse('miramar_pageversion_update', 
                                  kwargs={'slug': 'test',
                                          'version_tag': 'default'}),
                          {'body': u'New body',
                           'comment': u'This changes everything!'})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        pageversion_obj = PageVersion.objects.filter(
            page__slug=u'test',
            page__site=Site.objects.get_current(),
            version_tag=u'default').order_by('-revision')[0]
        self.assertEqual(pageversion_obj.body, u'New body')
        self.assertEqual(pageversion_obj.comment, u'This changes everything!')
        self.assertFalse(pageversion_obj.approved)
        self.assertEqual(pageversion_obj.author, self.editor)
        signal_data = signal_test.fired()
        self.assertEqual(len(signal_data), 1)
        self.assertEqual(signals.PAGEVERSION_UPDATED,
                         signal_data[0][0])

class TestPageVersionApprove(TestCase):
    fixtures = ['view_tests.json']

    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        can_approve = Permission.objects.get(codename='can_approve_pageversion')
        writer.user_permissions.add(can_approve)
        self.writer = writer
        signal_test.reset()
    
    def test_approve_permissions(self):
        c = Client()
        # anonymous of course can't approve
        response = c.get(reverse('miramar_pageversion_approve', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users may not approve
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_pageversion_approve', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])

        # privileged user can approve
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_approve', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 200)

    def test_approve_nonexistant_version(self):
        c = Client()
        
        # page has to exist. sorry. 
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_approve', 
                                 kwargs={'slug': 'non-existant-page',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 404)
        
        # if the page version doesn't exist, redirect back to update page
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_approve', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '10000'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        
        # if the page version doesn't exist, redirect back to update page
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_approve', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'bad-version',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        
    def test_approve(self):
        pageversion_obj = PageVersion.objects.get(
            page__slug__iexact='test',
            version_tag='default',
            revision=1)
        self.assertFalse(pageversion_obj.approved)
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_pageversion_approve', 
                                  kwargs={'slug': 'test',
                                          'version_tag': 'default',
                                          'revision': '1'}),
                          {})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        pageversion_obj = PageVersion.objects.get(
            page__slug__iexact='test',
            version_tag='default',
            revision=1,
            approved=True)

class TestPageVersionPublish(TestCase):
    fixtures = ['view_tests.json']

    def setUp(self):
        staff = User.objects.create_user('staff',
                                         'staff@example.com',
                                         'foobar')
        staff.is_staff = True
        staff.save()
        writer = User.objects.create_user('writer',
                                          'writer@example.com',
                                          'foobar')
        publish_pageversion = Permission.objects.get(codename='can_publish_pageversion')
        approve_pageversion = Permission.objects.get(codename='can_approve_pageversion')
        writer.user_permissions.add(approve_pageversion)
        writer.user_permissions.add(publish_pageversion)
        self.writer = writer
        signal_test.reset()
    
    def test_publish_permissions(self):
        c = Client()
        # anonymous of course can't publish
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])
        
        # unprivileged users may not publish
        c.login(username='staff', password='foobar')
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(site_settings.LOGIN_URL in response['location'])

        # privileged user can publish
        pageversion_obj = PageVersion.objects.get(
            page__slug__iexact='test',
            version_tag='default',
            revision=1)
        self.assertFalse(pageversion_obj.approved)
        pageversion_obj.approve(self.writer)
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 200)

    def test_publish_nonexistant_version(self):
        c = Client()
        
        # page has to exist. sorry. 
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'non-existant-page',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 404)
        
        # if the page version doesn't exist, redirect back to update page
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '10000'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        
        # if the page version isn't approved, redirect back to update page
        pageversion_obj = PageVersion.objects.get(
            page__slug__iexact='test',
            version_tag='default',
            revision=1)
        self.assertFalse(pageversion_obj.approved)
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'default',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        
        # if the page version doesn't exist, redirect back to update page
        c.login(username='writer', password='foobar')
        response = c.get(reverse('miramar_pageversion_publish', 
                                 kwargs={'slug': 'test',
                                         'version_tag': 'bad-version',
                                         'revision': '1'}))
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        
    def test_publish(self):
        pageversion_obj = PageVersion.objects.get(
            page__slug__iexact='test',
            version_tag='default',
            revision=1)
        self.assertFalse(pageversion_obj.approved)
        pageversion_obj.approve(self.writer)
        c = Client()
        c.login(username='writer', password='foobar')
        response = c.post(reverse('miramar_pageversion_publish', 
                                  kwargs={'slug': 'test',
                                          'version_tag': 'default',
                                          'revision': '1'}),
                          {})
        self.assertEqual(response.status_code, 302)
        self.assert_(response['location'].endswith(
            reverse('miramar_page_update', kwargs={'slug': 'test'})))
        page_obj = Page.on_site.get(slug__iexact='test')
        self.assertEqual(page_obj.published_version.id, pageversion_obj.id)
